from typing import Iterable

import scrapy
from scrapy import Request

from day13.day13.items import MoivieItem

"""
1、第一步先要对那个网址进行请求  https://login2.scrape.center  先登录
2、第二步  获取每一页的数据 对每一页做请求
3、第三步  对每一页做解析  得到每一页中所有电影的详情做请信息地址求
4、第四步  对得到的每一部电影详情的数据  并且对其进行保存到管道
保存到管道先要在items中创建MoivieItem类规定数据保存的格式并且定义字段为scrapy.Field字段
然后再到pipelines中定义DoubanExcelPipeLine管道类  将数据保存
注意： 在pipelines中管道类中的初始化方法为open_spider，结束管道操作为close_spider，并且每个方法中的参数都要包含spider 指传数据的哪个爬虫对象

"""

class Login2Spider(scrapy.Spider):
    name = "login2"
    allowed_domains = ["login2.scrape.center"]
    # start_urls = ["https://login2.scrape.center/login"]     #这里默认是使用get方法做请求但是我们首先需要爬取的页面为post请求因此不用

    def start_requests(self) -> Iterable[Request]:
        """
        执行登录login请求
        :return:
        """
        # yield scrapy.Request('https://login2.scrape.center',method='POST',body=)  #适合传的参数为str字符串类型
        yield scrapy.FormRequest(url='https://login2.scrape.center/login',formdata={
            'username': 'admin',
            'password': 'admin',
        })  #默认使用POST请求方式，如果接口是POST请求方式，请求体数据是表单类型，那么使用FormRequest
        #如果不是 就用Request(method='POST',body=json.dumps({
        #                              'username': 'admin',
        #                              'password': 'admin',
        #                      }))


    def parse(self, response):
        """
        执行完login请求，对login请求的响应对象进行解析，以及跟进后续请求 对page1做请求
        得到登录后的响应数据
        这里对page1做请求只需要将这个请求给到调度器  引擎会自动获取调度器中的请求  并且交给下载器做请求

        构建每页数据请求，交给引擎，引擎放入调度器进行处理，下载器进行网络请求的得到响应，中间是异步的  异步处理多个请求
        :param response:
        :return:
        """
        #callback 指定下载器在网络请求获得到响应对象后，传递给爬虫的哪个方法进行解析(数据操作)
        # yield scrapy.Request('https://login2.scrape.center/page/1', callback=self.page_parse)
        for i in range(1,11):
            yield scrapy.Request(f'https://login2.scrape.center/page/{i}', callback=self.page_parse)

    def page_parse(self, response):
        """
        解析每一页响应，以及后续的请求
        得到每页的响应数据 得到每部电影的详情地址
        :param response:
        :return:
        """
        # print(response.text)
        # print(response.request.headers)
        #getall()获取所有元素的属性值
        details_urls = response.xpath('//div[contains(@class,"m-t is-hover-shadow")]//a[@class="name"]/@href').getall()
        # print(details_urls,len(details_urls))

        #获取每个电影的详情地址  将每个电影的详情请求地址放到调度器中  引擎获取调度器中的请求 在下载器中做请求
        for url in details_urls:
            url = 'https://login2.scrape.center' + url
            print(url)
            yield scrapy.Request(url,callback=self.parse_detail)

    def parse_detail(self, response):
        """
        电影详情响应解析  以及后续的请求分析
        :param response:
        :return:
        """
        content_div = response.xpath('//div[@class="item el-row"]')[0]  #标签就直接取值

        item = MoivieItem()

        item['title'] = content_div.xpath('.//h2[@class="m-b-sm"]/text()').get()    #text()拿文本的属性值就要用get方法或getall方法
        item['content'] = content_div.xpath('.//div[@class="drama"]/p/text()').get().strip()

        yield item

